package org.example.compare.schedule;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import cn.hutool.core.lang.Pair;
import org.example.compare.dto.*;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 测试数据生成器类，用于为calculateItem_14函数生成测试数据
 * 该函数使用到的非函数参数列表外部变量包括:
 * 1. SchData.pPositionDtos - 工位数据
 * 2. SchData.workerToTechType - 工人技能类型数据
 * 3. hProcessSet - 需要进行排产的工序集
 * 4. sPositionsScore - 可以排产的工位
 * 5. hScoreByProcess - 按工序查找的分数表
 */
public class CalculateItem14TestDataGenerator {

    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final Random random = new Random();

    static {
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 生成随机测试数据并保存到文件
     */
    public static void generateRandomTestData(int iteration) throws IOException {
        String basePath = "../../test_data/calculateItem_14/random_case_" + iteration;
        File baseDir = new File(basePath);

        // 清空文件夹
        clearDirectory(baseDir);

        if (!baseDir.exists()) {
            baseDir.mkdirs();
        }

        // 先生成可以排产的工位数据
        Set<Long> sPositionsScore = generatePositionScoreData(basePath);
        
        // 再生成工位数据，确保包含了所有可排产的工位
        Map<Long, PositionDto> pPositionDtos = generatePositionDtosData(basePath, sPositionsScore);
        
        // 生成其他数据
        Map<String, Object> workerToTechType = generateWorkerToTechTypeData(basePath, pPositionDtos);
        Map<Long, OrderProcess> hProcessSet = generateProcessSetData(basePath, pPositionDtos, workerToTechType);
        generateScoreByProcessData(basePath, hProcessSet, sPositionsScore);
        generateFunctionParams(basePath);
    }

    /**
     * 生成手动测试数据并保存到文件
     */
    public static void generateManualTestData(int caseNumber) throws IOException {
        String basePath = "../../test_data/calculateItem_14/manual_case_" + caseNumber;
        File baseDir = new File(basePath);

        // 清空文件夹
        clearDirectory(baseDir);

        if (!baseDir.exists()) {
            baseDir.mkdirs();
        }

        if (caseNumber == 1) {
            generateManualTestCase1(basePath);
        } else if (caseNumber == 2) {
            generateManualTestCase2(basePath);
        }
    }

    /**
     * 生成手动测试案例1 - 基本正常情况
     */
    private static void generateManualTestCase1(String basePath) throws IOException {
        // 生成工位数据
        Map<Long, PositionDto> pPositionDtos = new HashMap<>();

        // 工位1
        PositionDto position1 = new PositionDto();
        position1.setPositionId(10001L);
        position1.setWorkerId(20001L);
        pPositionDtos.put(10001L, position1);

        // 工位2
        PositionDto position2 = new PositionDto();
        position2.setPositionId(10002L);
        position2.setWorkerId(20002L);
        pPositionDtos.put(10002L, position2);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/pPositionDtos.json"), pPositionDtos);

        // 生成工人技能类型数据
        Map<String, Object> workerToTechType = new HashMap<>();

        // 工人1的技能类型数据
        WorkerTechType workerTechType1 = new WorkerTechType();
        workerTechType1.setId(30001L);
        workerTechType1.setWorkerId(20001L);
        workerTechType1.setProcessType("TYPE_A");
        workerTechType1.setAvgProcessRate(95.0);
        
        Map<String, Object> workerTechTypeMap1 = new HashMap<>();
        workerTechTypeMap1.put("workerId", 20001L);
        workerTechTypeMap1.put("processType", "TYPE_A");
        workerTechTypeMap1.put("value", workerTechType1);
        workerToTechType.put("20001_TYPE_A", workerTechTypeMap1);

        // 工人2的技能类型数据
        WorkerTechType workerTechType2 = new WorkerTechType();
        workerTechType2.setId(30002L);
        workerTechType2.setWorkerId(20002L);
        workerTechType2.setProcessType("TYPE_A");
        workerTechType2.setAvgProcessRate(85.0);
        
        Map<String, Object> workerTechTypeMap2 = new HashMap<>();
        workerTechTypeMap2.put("workerId", 20002L);
        workerTechTypeMap2.put("processType", "TYPE_A");
        workerTechTypeMap2.put("value", workerTechType2);
        workerToTechType.put("20002_TYPE_A", workerTechTypeMap2);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/workerToTechType.json"), workerToTechType);

        // 生成工序集数据
        Map<Long, OrderProcess> hProcessSet = new HashMap<>();

        // 工序1 (正常状态)
        OrderDto dummyOrder = OrderDto.InitOrder();
        OrderProcess process1 = OrderProcess.InitOrderProcess(dummyOrder);
        process1.setProcessId(1001L);
        process1.setOrderProcessId(1001L);
        process1.setMProcessType("TYPE_A"); // 与工人的技能类型匹配

        ProcessSch scheduling1 = new ProcessSch();
        scheduling1.setMbHoldFlag(false);
        scheduling1.setMbNGFlag(false);

        // 设置可做工位
        Set<Long> posCanDo1 = new HashSet<>();
        posCanDo1.add(10001L);
        posCanDo1.add(10002L);
        scheduling1.setMPosCanDo(posCanDo1);

        process1.setMScheduling(scheduling1);
        hProcessSet.put(1001L, process1);

        // 工序2 (挂起状态)
        OrderProcess process2 = OrderProcess.InitOrderProcess(dummyOrder);
        process2.setProcessId(1002L);
        process2.setOrderProcessId(1002L);
        process2.setMProcessType("TYPE_B"); // 与工人的技能类型不匹配

        ProcessSch scheduling2 = new ProcessSch();
        scheduling2.setMbHoldFlag(true); // 挂起状态
        scheduling2.setMbNGFlag(false);

        // 设置可做工位
        Set<Long> posCanDo2 = new HashSet<>();
        posCanDo2.add(10001L);
        scheduling2.setMPosCanDo(posCanDo2);

        process2.setMScheduling(scheduling2);
        hProcessSet.put(1002L, process2);

        // 工序3 (NG状态)
        OrderProcess process3 = OrderProcess.InitOrderProcess(dummyOrder);
        process3.setProcessId(1003L);
        process3.setOrderProcessId(1003L);
        process3.setMProcessType("TYPE_C"); // 与工人的技能类型不匹配

        ProcessSch scheduling3 = new ProcessSch();
        scheduling3.setMbHoldFlag(false);
        scheduling3.setMbNGFlag(true); // NG状态

        // 设置可做工位
        Set<Long> posCanDo3 = new HashSet<>();
        posCanDo3.add(10002L);
        scheduling3.setMPosCanDo(posCanDo3);

        process3.setMScheduling(scheduling3);
        hProcessSet.put(1003L, process3);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/hProcessSet.json"), hProcessSet);

        // 生成可以排产的工位数据
        Set<Long> sPositionsScore = new HashSet<>();
        sPositionsScore.add(10001L);
        sPositionsScore.add(10002L);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/sPositionsScore.json"), sPositionsScore);

        // 生成按工序查找的分数表数据
        Map<Long, List<Score>> hScoreByProcess = new HashMap<>();

        // 工序1的分数
        List<Score> scores1 = new ArrayList<>();
        Score score1_1 = new Score();
        score1_1.setPositionId(10001L);
        score1_1.setTotal(80.0);
        double[] scoreItems1 = new double[20];
        Arrays.fill(scoreItems1, 5.0);
        scoreItems1[15] = 10.0; // 设置索引15的分数项
        score1_1.setScoreItem(scoreItems1);
        scores1.add(score1_1);

        Score score1_2 = new Score();
        score1_2.setPositionId(10002L);
        score1_2.setTotal(75.0);
        double[] scoreItems2 = new double[20];
        Arrays.fill(scoreItems2, 4.5);
        scoreItems2[15] = 8.0; // 设置索引15的分数项
        score1_2.setScoreItem(scoreItems2);
        scores1.add(score1_2);

        hScoreByProcess.put(1001L, scores1);

        // 工序2的分数 (挂起状态)
        List<Score> scores2 = new ArrayList<>();
        Score score2_1 = new Score();
        score2_1.setPositionId(10001L);
        score2_1.setTotal(85.0);
        double[] scoreItems3 = new double[20];
        Arrays.fill(scoreItems3, 6.0);
        scoreItems3[15] = 12.0; // 设置索引15的分数项
        score2_1.setScoreItem(scoreItems3);
        scores2.add(score2_1);

        hScoreByProcess.put(1002L, scores2);

        // 工序3的分数 (NG状态)
        List<Score> scores3 = new ArrayList<>();
        Score score3_1 = new Score();
        score3_1.setPositionId(10002L);
        score3_1.setTotal(90.0);
        double[] scoreItems4 = new double[20];
        Arrays.fill(scoreItems4, 6.5);
        scoreItems4[15] = 15.0; // 设置索引15的分数项
        score3_1.setScoreItem(scoreItems4);
        scores3.add(score3_1);

        hScoreByProcess.put(1003L, scores3);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/hScoreByProcess.json"), hScoreByProcess);

        // 生成函数参数
        Map<String, Object> functionParams = new HashMap<>();
        functionParams.put("ratio", 0.1);
        objectMapper.writeValue(new File(basePath + "/testCases.json"), functionParams);
    }

    /**
     * 生成手动测试案例2 - 包含多种技能类型匹配情况
     */
    private static void generateManualTestCase2(String basePath) throws IOException {
        // 生成工位数据
        Map<Long, PositionDto> pPositionDtos = new HashMap<>();

        // 工位1 - 高技能工人
        PositionDto position1 = new PositionDto();
        position1.setPositionId(20001L);
        position1.setWorkerId(30001L);
        pPositionDtos.put(20001L, position1);

        // 工位2 - 中等技能工人
        PositionDto position2 = new PositionDto();
        position2.setPositionId(20002L);
        position2.setWorkerId(30002L);
        pPositionDtos.put(20002L, position2);

        // 工位3 - 低技能工人
        PositionDto position3 = new PositionDto();
        position3.setPositionId(20003L);
        position3.setWorkerId(30003L);
        pPositionDtos.put(20003L, position3);

        // 工位4 - 无技能数据的工人
        PositionDto position4 = new PositionDto();
        position4.setPositionId(20004L);
        position4.setWorkerId(30004L);
        pPositionDtos.put(20004L, position4);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/pPositionDtos.json"), pPositionDtos);

        // 生成工人技能类型数据
        Map<String, Object> workerToTechType = new HashMap<>();

        // 工人1的技能类型数据 - 高技能
        WorkerTechType workerTechType1 = new WorkerTechType();
        workerTechType1.setId(40001L);
        workerTechType1.setWorkerId(30001L);
        workerTechType1.setProcessType("TYPE_X");
        workerTechType1.setAvgProcessRate(98.0);
        
        Map<String, Object> workerTechTypeMap1 = new HashMap<>();
        workerTechTypeMap1.put("workerId", 30001L);
        workerTechTypeMap1.put("processType", "TYPE_X");
        workerTechTypeMap1.put("value", workerTechType1);
        workerToTechType.put("30001_TYPE_X", workerTechTypeMap1);

        // 工人2的技能类型数据 - 中等技能
        WorkerTechType workerTechType2 = new WorkerTechType();
        workerTechType2.setId(40002L);
        workerTechType2.setWorkerId(30002L);
        workerTechType2.setProcessType("TYPE_X");
        workerTechType2.setAvgProcessRate(80.0);
        
        Map<String, Object> workerTechTypeMap2 = new HashMap<>();
        workerTechTypeMap2.put("workerId", 30002L);
        workerTechTypeMap2.put("processType", "TYPE_X");
        workerTechTypeMap2.put("value", workerTechType2);
        workerToTechType.put("30002_TYPE_X", workerTechTypeMap2);

        // 工人3的技能类型数据 - 低技能
        WorkerTechType workerTechType3 = new WorkerTechType();
        workerTechType3.setId(40003L);
        workerTechType3.setWorkerId(30003L);
        workerTechType3.setProcessType("TYPE_X");
        workerTechType3.setAvgProcessRate(60.0);
        
        Map<String, Object> workerTechTypeMap3 = new HashMap<>();
        workerTechTypeMap3.put("workerId", 30003L);
        workerTechTypeMap3.put("processType", "TYPE_X");
        workerTechTypeMap3.put("value", workerTechType3);
        workerToTechType.put("30003_TYPE_X", workerTechTypeMap3);

        // 工人4的技能类型数据 - 不匹配的技能类型
        WorkerTechType workerTechType4 = new WorkerTechType();
        workerTechType4.setId(40004L);
        workerTechType4.setWorkerId(30004L);
        workerTechType4.setProcessType("TYPE_Y"); // 与工序的技能类型不匹配
        workerTechType4.setAvgProcessRate(75.0);
        
        Map<String, Object> workerTechTypeMap4 = new HashMap<>();
        workerTechTypeMap4.put("workerId", 30004L);
        workerTechTypeMap4.put("processType", "TYPE_Y");
        workerTechTypeMap4.put("value", workerTechType4);
        workerToTechType.put("30004_TYPE_Y", workerTechTypeMap4);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/workerToTechType.json"), workerToTechType);

        // 生成工序集数据
        Map<Long, OrderProcess> hProcessSet = new HashMap<>();

        // 工序1 - 与所有工位技能类型匹配
        OrderDto dummyOrder = OrderDto.InitOrder();
        OrderProcess process1 = OrderProcess.InitOrderProcess(dummyOrder);
        process1.setProcessId(2001L);
        process1.setOrderProcessId(2001L);
        process1.setMProcessType("TYPE_X"); // 与工位1-3的技能类型匹配

        ProcessSch scheduling1 = new ProcessSch();
        scheduling1.setMbHoldFlag(false);
        scheduling1.setMbNGFlag(false);

        // 设置可做工位
        Set<Long> posCanDo1 = new HashSet<>();
        posCanDo1.add(20001L);
        posCanDo1.add(20002L);
        posCanDo1.add(20003L);
        posCanDo1.add(20004L);
        scheduling1.setMPosCanDo(posCanDo1);

        process1.setMScheduling(scheduling1);
        hProcessSet.put(2001L, process1);

        // 工序2 - 无匹配的技能类型
        OrderProcess process2 = OrderProcess.InitOrderProcess(dummyOrder);
        process2.setProcessId(2002L);
        process2.setOrderProcessId(2002L);
        process2.setMProcessType("TYPE_Z"); // 与任何工位的技能类型都不匹配

        ProcessSch scheduling2 = new ProcessSch();
        scheduling2.setMbHoldFlag(false);
        scheduling2.setMbNGFlag(false);

        // 设置可做工位
        Set<Long> posCanDo2 = new HashSet<>();
        posCanDo2.add(20001L);
        posCanDo2.add(20002L);
        scheduling2.setMPosCanDo(posCanDo2);

        process2.setMScheduling(scheduling2);
        hProcessSet.put(2002L, process2);

        // 工序3 - 空的技能类型
        OrderProcess process3 = OrderProcess.InitOrderProcess(dummyOrder);
        process3.setProcessId(2003L);
        process3.setOrderProcessId(2003L);
        process3.setMProcessType(""); // 空的技能类型

        ProcessSch scheduling3 = new ProcessSch();
        scheduling3.setMbHoldFlag(false);
        scheduling3.setMbNGFlag(false);

        // 设置可做工位
        Set<Long> posCanDo3 = new HashSet<>();
        posCanDo3.add(20003L);
        posCanDo3.add(20004L);
        scheduling3.setMPosCanDo(posCanDo3);

        process3.setMScheduling(scheduling3);
        hProcessSet.put(2003L, process3);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/hProcessSet.json"), hProcessSet);

        // 生成可以排产的工位数据
        Set<Long> sPositionsScore = new HashSet<>();
        sPositionsScore.add(20001L);
        sPositionsScore.add(20002L);
        sPositionsScore.add(20003L);
        sPositionsScore.add(20004L);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/sPositionsScore.json"), sPositionsScore);

        // 生成按工序查找的分数表数据
        Map<Long, List<Score>> hScoreByProcess = new HashMap<>();

        // 工序1的分数 - 有多个匹配的技能类型
        List<Score> scores1 = new ArrayList<>();
        Score score1_1 = new Score();
        score1_1.setPositionId(20001L);
        score1_1.setTotal(95.0);
        double[] scoreItems1 = new double[20];
        Arrays.fill(scoreItems1, 8.0);
        scoreItems1[15] = 25.0; // 设置索引15的分数项
        score1_1.setScoreItem(scoreItems1);
        scores1.add(score1_1);

        Score score1_2 = new Score();
        score1_2.setPositionId(20002L);
        score1_2.setTotal(90.0);
        double[] scoreItems2 = new double[20];
        Arrays.fill(scoreItems2, 7.5);
        scoreItems2[15] = 22.0; // 设置索引15的分数项
        score1_2.setScoreItem(scoreItems2);
        scores1.add(score1_2);

        Score score1_3 = new Score();
        score1_3.setPositionId(20003L);
        score1_3.setTotal(85.0);
        double[] scoreItems3 = new double[20];
        Arrays.fill(scoreItems3, 7.0);
        scoreItems3[15] = 20.0; // 设置索引15的分数项
        score1_3.setScoreItem(scoreItems3);
        scores1.add(score1_3);

        Score score1_4 = new Score();
        score1_4.setPositionId(20004L);
        score1_4.setTotal(80.0);
        double[] scoreItems4 = new double[20];
        Arrays.fill(scoreItems4, 6.5);
        scoreItems4[15] = 18.0; // 设置索引15的分数项
        score1_4.setScoreItem(scoreItems4);
        scores1.add(score1_4);

        hScoreByProcess.put(2001L, scores1);

        // 工序2的分数 - 无匹配的技能类型
        List<Score> scores2 = new ArrayList<>();
        Score score2_1 = new Score();
        score2_1.setPositionId(20001L);
        score2_1.setTotal(75.0);
        double[] scoreItems5 = new double[20];
        Arrays.fill(scoreItems5, 6.0);
        scoreItems5[15] = 15.0; // 设置索引15的分数项
        score2_1.setScoreItem(scoreItems5);
        scores2.add(score2_1);

        Score score2_2 = new Score();
        score2_2.setPositionId(20002L);
        score2_2.setTotal(70.0);
        double[] scoreItems6 = new double[20];
        Arrays.fill(scoreItems6, 5.5);
        scoreItems6[15] = 12.0; // 设置索引15的分数项
        score2_2.setScoreItem(scoreItems6);
        scores2.add(score2_2);

        hScoreByProcess.put(2002L, scores2);

        // 工序3的分数 - 空的技能类型
        List<Score> scores3 = new ArrayList<>();
        Score score3_1 = new Score();
        score3_1.setPositionId(20003L);
        score3_1.setTotal(65.0);
        double[] scoreItems7 = new double[20];
        Arrays.fill(scoreItems7, 5.0);
        scoreItems7[15] = 10.0; // 设置索引15的分数项
        score3_1.setScoreItem(scoreItems7);
        scores3.add(score3_1);

        Score score3_2 = new Score();
        score3_2.setPositionId(20004L);
        score3_2.setTotal(60.0);
        double[] scoreItems8 = new double[20];
        Arrays.fill(scoreItems8, 4.5);
        scoreItems8[15] = 8.0; // 设置索引15的分数项
        score3_2.setScoreItem(scoreItems8);
        scores3.add(score3_2);

        hScoreByProcess.put(2003L, scores3);

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/hScoreByProcess.json"), hScoreByProcess);

        // 生成函数参数
        Map<String, Object> functionParams = new HashMap<>();
        functionParams.put("ratio", 0.15);
        objectMapper.writeValue(new File(basePath + "/testCases.json"), functionParams);
    }

    /**
     * 清空指定目录下的所有文件
     *
     * @param directory 要清空的目录
     * @throws IOException IO异常
     */
    private static void clearDirectory(File directory) throws IOException {
        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isFile()) {
                        Files.delete(file.toPath());
                    }
                }
            }
        }
    }

    /**
     * 生成工位数据
     */
    private static Map<Long, PositionDto> generatePositionDtosData(String basePath, Set<Long> sPositionsScore) throws IOException {
        Map<Long, PositionDto> pPositionDtos = new HashMap<>();

        // 确保所有可排产的工位都在工位数据中
        for (Long positionId : sPositionsScore) {
            PositionDto position = new PositionDto();
            long workerId = 20000L + random.nextInt(90000); // 20000-99999的工人ID
            position.setPositionId(positionId);
            position.setWorkerId(workerId);

            pPositionDtos.put(positionId, position);
        }

        // 随机添加额外的工位数据
        int extraPositionCount = random.nextInt(6); // 0-5个额外工位

        for (int i = 0; i < extraPositionCount; i++) {
            PositionDto position = new PositionDto();
            long positionId = 10000L + random.nextInt(90000); // 10000-99999的工位ID
            
            // 确保不重复
            while (pPositionDtos.containsKey(positionId)) {
                positionId = 10000L + random.nextInt(90000);
            }
            
            long workerId = 20000L + random.nextInt(90000); // 20000-99999的工人ID
            position.setPositionId(positionId);
            position.setWorkerId(workerId);

            pPositionDtos.put(positionId, position);
        }

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/pPositionDtos.json"), pPositionDtos);

        return pPositionDtos;
    }
    
    private static Map<Long, PositionDto> generatePositionDtosData(String basePath) throws IOException {
        Map<Long, PositionDto> pPositionDtos = new HashMap<>();

        // 随机生成工位数量 5-10个
        int positionCount = 5 + random.nextInt(6);

        for (int i = 0; i < positionCount; i++) {
            PositionDto position = new PositionDto();
            long positionId = 10000L + random.nextInt(90000); // 10000-99999的工位ID
            long workerId = 20000L + random.nextInt(90000); // 20000-99999的工人ID
            position.setPositionId(positionId);
            position.setWorkerId(workerId);

            pPositionDtos.put(positionId, position);
        }

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/pPositionDtos.json"), pPositionDtos);

        return pPositionDtos;
    }

    /**
     * 生成工人技能类型数据
     */
    private static Map<String, Object> generateWorkerToTechTypeData(String basePath,
                                                                 Map<Long, PositionDto> pPositionDtos) throws IOException {
        Map<String, Object> workerToTechType = new HashMap<>();

        // 获取工位列表
        List<PositionDto> positions = new ArrayList<>(pPositionDtos.values());

        // 为每个工位生成技能类型数据
        for (PositionDto position : positions) {
            // 每个工人有1-3种技能类型
            int skillCount = 1 + random.nextInt(3);
            for (int i = 0; i < skillCount; i++) {
                WorkerTechType workerTechType = new WorkerTechType();
                long id = 30000L + random.nextInt(90000); // 30000-99999的ID
                String processType = "TYPE_" + (char) ('A' + random.nextInt(26)); // TYPE_A 到 TYPE_Z

                workerTechType.setId(id);
                workerTechType.setWorkerId(position.getWorkerId());
                workerTechType.setProcessType(processType);
                // 效率值保留两位小数
                double avgProcessRate = 50.0 + random.nextDouble() * 50.0; // 50-100的效率值
                avgProcessRate = new BigDecimal(avgProcessRate).setScale(2, RoundingMode.HALF_UP).doubleValue();
                workerTechType.setAvgProcessRate(avgProcessRate);

                Map<String, Object> workerTechTypeMap = new HashMap<>();
                workerTechTypeMap.put("workerId", position.getWorkerId());
                workerTechTypeMap.put("processType", processType);
                workerTechTypeMap.put("value", workerTechType);
                workerToTechType.put(position.getWorkerId() + "_" + processType, workerTechTypeMap);
            }
        }

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/workerToTechType.json"), workerToTechType);

        return workerToTechType;
    }

    /**
     * 生成工序集数据
     */
    private static Map<Long, OrderProcess> generateProcessSetData(String basePath,
                                                                 Map<Long, PositionDto> pPositionDtos,
                                                                 Map<String, Object> workerToTechType) throws IOException {
        Map<Long, OrderProcess> hProcessSet = new HashMap<>();

        // 随机生成工序数量 3-8个
        int processCount = 3 + random.nextInt(6);

        OrderDto dummyOrder = OrderDto.InitOrder();

        List<Long> positionIds = new ArrayList<>(pPositionDtos.keySet());

        for (int i = 0; i < processCount; i++) {
            OrderProcess process = OrderProcess.InitOrderProcess(dummyOrder);
            long processId = 1000L + i * 10 + random.nextInt(10);
            process.setProcessId(processId);
            process.setOrderProcessId(processId);

            // 随机设置技能类型
            if (random.nextDouble() < 0.8) { // 80%概率设置非空技能类型
                process.setMProcessType("TYPE_" + (char) ('A' + random.nextInt(26))); // TYPE_A 到 TYPE_Z
            } else {
                process.setMProcessType(""); // 20%概率设置空技能类型
            }

            ProcessSch scheduling = new ProcessSch();
            scheduling.setMbHoldFlag(random.nextDouble() < 0.1); // 10%概率为挂起状态
            scheduling.setMbNGFlag(random.nextDouble() < 0.1); // 10%概率为NG状态

            // 设置可做工位集合，确保这些工位在pPositionDtos中存在
            Set<Long> posCanDo = new HashSet<>();
            int posCount = Math.min(2 + random.nextInt(5), positionIds.size()); // 2-6个工位
            Collections.shuffle(positionIds);
            for (int j = 0; j < posCount; j++) {
                posCanDo.add(positionIds.get(j));
            }
            scheduling.setMPosCanDo(posCanDo);

            process.setMScheduling(scheduling);
            hProcessSet.put(processId, process);
        }

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/hProcessSet.json"), hProcessSet);

        return hProcessSet;
    }

    /**
     * 生成可以排产的工位数据
     */
    private static Set<Long> generatePositionScoreData(String basePath) throws IOException {
        Set<Long> sPositionsScore = new HashSet<>();

        // 随机生成工位数量 5-10个
        int positionCount = 5 + random.nextInt(6);

        // 添加测试工位ID
        for (int i = 0; i < positionCount; i++) {
            sPositionsScore.add((long) (10000 + random.nextInt(90000))); // 10000-99999的工位ID
        }

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/sPositionsScore.json"), sPositionsScore);

        return sPositionsScore;
    }

    /**
     * 生成按工序查找的分数表数据
     */
    private static void generateScoreByProcessData(String basePath, Map<Long, OrderProcess> hProcessSet,
                                                   Set<Long> sPositionsScore) throws IOException {
        Map<Long, List<Score>> hScoreByProcess = new HashMap<>();

        // 使用已生成的工序ID来创建分数数据
        List<Long> processIds = new ArrayList<>(hProcessSet.keySet());

        for (Long processId : processIds) {
            List<Score> scores = new ArrayList<>();

            // 获取工位ID列表，确保只使用sPositionsScore中的工位
            List<Long> positionIds = new ArrayList<>(sPositionsScore);
            Collections.shuffle(positionIds); // 随机打乱

            // 每个工序对应1-5个工位分数（不超过工位总数）
            int scoreCount = Math.min(1 + random.nextInt(5), positionIds.size());
            for (int j = 0; j < scoreCount; j++) {
                Score score = new Score();
                score.setPositionId(positionIds.get(j));
                // 总分保留两位小数
                double total = random.nextDouble() * 100; // 0-100的总分
                total = new BigDecimal(total).setScale(2, RoundingMode.HALF_UP).doubleValue();
                score.setTotal(total);

                // 初始化分数项数组，包含随机分数，每项保留两位小数
                double[] scoreItems = new double[20];
                for (int k = 0; k < scoreItems.length; k++) {
                    double item = random.nextDouble() * 50; // 0-50的分数项
                    item = new BigDecimal(item).setScale(2, RoundingMode.HALF_UP).doubleValue();
                    scoreItems[k] = item;
                }
                // 特别设置索引15的分数项
                double item15 = random.nextDouble() * 30; // 0-30的分数项
                item15 = new BigDecimal(item15).setScale(2, RoundingMode.HALF_UP).doubleValue();
                scoreItems[15] = item15;
                score.setScoreItem(scoreItems);

                scores.add(score);
            }

            hScoreByProcess.put(processId, scores);
        }

        // 保存到文件
        objectMapper.writeValue(new File(basePath + "/hScoreByProcess.json"), hScoreByProcess);
    }

    /**
     * 生成函数参数
     */
    private static void generateFunctionParams(String basePath) throws IOException {
        Map<String, Object> functionParams = new HashMap<>();
        // 生成 0.01 到 1.0 之间的随机 ratio 值，保留两位小数
        double randomRatio = 0.01 + random.nextDouble() * 0.99;
        randomRatio = new BigDecimal(randomRatio).setScale(2, RoundingMode.HALF_UP).doubleValue();
        functionParams.put("ratio", randomRatio);
        objectMapper.writeValue(new File(basePath + "/testCases.json"), functionParams);
    }

    public static void main(String[] args) {
        try {
            // 确保主目录存在
            File mainDir = new File("../../test_data/calculateItem_14");
            if (!mainDir.exists()) {
                mainDir.mkdirs();
            }

            // 生成50组随机测试数据
            for (int i = 1; i <= 50; i++) {
                generateRandomTestData(i);
                System.out.println("随机测试数据集 " + i + " 已成功生成");
            }

            // 生成2个手动测试案例
            for (int i = 1; i <= 2; i++) {
                generateManualTestData(i);
                System.out.println("手动测试案例 " + i + " 已成功生成");
            }

            System.out.println("所有测试数据已成功生成并保存到../../test_data/calculateItem_14目录下");
        } catch (IOException e) {
            System.err.println("生成测试数据时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}